package com.softdev.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.softdev.pojo.Module;
import com.softdev.pojo.Project;
import com.softdev.pojo.User;
import com.softdev.repo.ModuleRepository;
import com.softdev.repo.ProjectRepository;
import com.softdev.service.ModuleService;
import com.softdev.utils.UserIdFindingUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class ModuleServiceImpl implements ModuleService {

    @Resource
    private ProjectRepository projectRepository;

    @Resource
    private ModuleRepository moduleRepository;

    @Override
    public boolean hasAuthor(Long moduleId) {

        Module module = moduleRepository.findById(moduleId).get();
        List<User> users = module.getUsers();

        Long userId = UserIdFindingUtil.getUserId();

        for (User user : users) {
            if (Objects.equals(userId, user.getId())) {
                return true;
            }
        }

        return false;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean update(Long projectId , Long moduleId) throws JsonProcessingException {

        Project project = projectRepository.findByIdWithLazyProperties(projectId);
        ObjectMapper objectMapper = new ObjectMapper();
        String stage = project.getStages();
        List<String> stages = objectMapper.readValue(stage , new TypeReference<List<String>>() {});
        int stageNum = stages.size();

        Set<Module> modules = projectRepository.findModules(project.getId());

        modules = modules.stream().peek(module -> {

            if (Objects.equals(moduleId, module.getId())) {
                module.setCur(Math.min(module.getCur() + 1 , stageNum));
            }

        }).collect(Collectors.toSet());

        project.setModules(modules);
        project.updateCur();
        project.updateStatus();

        projectRepository.save(project);

        return true;
    }

    @Override
    public boolean rollback(Long projectId, Long moduleId) throws JsonProcessingException {

        Project project = projectRepository.findByIdWithLazyProperties(projectId);
        Module module = moduleRepository.findById(moduleId).get();
        module.setCur(Math.max(module.getCur() - 1 , 0));
        moduleRepository.save(module);

        Set<Module> modules = projectRepository.findModules(project.getId());

        modules = modules.stream().peek(item -> {

            if (Objects.equals(moduleId, item.getId())) {
                item.setCur(Math.max(item.getCur() - 1 , 0));
            }

        }).collect(Collectors.toSet());

        project.setModules(modules);
        project.updateCur();
        project.updateStatus();

        projectRepository.save(project);

        return true;
    }
}
